如何管理游戏数据使用 SQLite 数据库本页总览使用 SQLite 数据库 Dora SSR 引 擎为开发者提供了 SQLite 数据库的集成,用于管理和查询大量游戏数据,以及进行关键游戏数据的持久化存储。本教程将带您从零开始,逐步了解如何使用 Dora 的数据库功能。 1. 引言 在游戏开发中,经常需要管理大量的游戏数据,如玩家信息. 游戏物品. 关卡配置等。使用数据库可以高效地存储和检索这些数据。Dora SSR 引擎集成了 SQLite 数据库,提供了一系列简单易用的接口,让您可以轻松地进行数据库操作。 1.1 初识数据库操作 在开始之前,确保您已了解以下概念: 数据库(Database):存储和管理数据的系统。 数据表(Table):数据库中的数据存储结构,由行和列组成。 行(Row):表中的一条记录。 列(Column):表中某个属性的集合。 2. DB 类简介 DB 类是 Dora 提供的用于数据库操作的核心类。通过这个类,您可以执行以下操作: 检查数据表是否存在 执行 SQL 查询 插入. 更新. 删除数据 执行事务 进行异步操作 2.1 DB 类相关重要概念 Column:表示数据库列的数据类型,可以是 integer. number. string 或 boolean。 特别提示在 Dora SSR 中数据库列的 boolean 类型仅支持 false 值,用于表示数据库中的空值(NULL)。如果需要在数据库中存储布尔值,需要使用数值类型的 0 和 1 来代替 false 和 true。 Row:表示数据库中的一行数据,通常是一个包含多个 Column 的 Lua 表。 SQL:表示 SQL 查询语句,可以是字符串或包含参数的字符串加上参数表。 3. 基本操作示例 下面,我们将通过一些基本操作来熟悉 DB 类的使用。 3.1 检查数据表是否存在 在操作数据库之前,通常需要确认某个数据表是否存在。可以使用 exist 方法: LuaTealTypeScriptYueScriptlocal tableExists = DB:exist("test_table")print(tableExists and "表存在" or "表不存在")local tableExists = DB:exist("test_table")print(tableExists and "表存在" or "表不存在")const tableExists = DB.exist("test_table");print(tableExists ? "表存在" : "表不存在");tableExists = DB\exist "test_table"print tableExists and "表存在" or "表不存在" 3.2 创建和删除数据表 可以使用 exec 方法执行创建和删除表的 SQL 语句: LuaTealTypeScriptYueScript-- 删除名为 test_table 的数据表(如果存在)DB:exec("DROP TABLE IF EXISTS test_table")-- 创建名为 test_table 的数据表DB:exec("CREATE TABLE test_table (id INTEGER PRIMARY KEY, value TEXT)")-- 删除名为 test_table 的数据表(如果存在)DB.exec("DROP TABLE IF EXISTS test_table")-- 创建名为 test_table 的数据表DB:exec("CREATE TABLE test_table (id INTEGER PRIMARY KEY, value TEXT)")// 删除名为 test_table 的数据表(如果存在)DB.exec("DROP TABLE IF EXISTS test_table");// 创建名为 test_table 的数据表DB.exec("CREATE TABLE test_table (id INTEGER PRIMARY KEY, value TEXT)");-- 删除名为 test_table 的数据表(如果存在)DB\exec "DROP TABLE IF EXISTS test_table"-- 创建名为 test_table 的数据表DB\exec "CREATE TABLE test_table (id INTEGER PRIMARY KEY, value TEXT)" 3.3 插入数据 使用 insert 方法可以将数据插入到表中: LuaTealTypeScriptYueScriptlocal success = DB:insert("test_table", { {1, "Hello"}, {2, "World"}})print(success and "插入成功" or "插入失败")local success = DB:insert("test_table", { {1, "Hello"}, {2, "World"}})print(success and "插入成功" or "插入失败")const success = DB.insert("test_table", [ [1, "Hello"], [2, "World"]]);print(success ? "插入成功" : "插入失败");success = DB\insert "test_table", [ [1, "Hello"], [2, "World"]]print success and "插入成功" or "插入失败" 3.4 查询数据 使用 query 方法可以从表中查询数据: LuaTealTypeScriptYueScriptlocal results = DB:query("SELECT * FROM test_table")for _, row in ipairs(results) do print("ID:", row[1], "Value:", row[2])endlocal results = DB:query("SELECT * FROM test_table")if not results is nil then for _, row in ipairs(results) do print("ID:", row[1], "Value:", row[2]) endendconst results = DB.query("SELECT * FROM test_table");if (results) { for (const [id, value] of results) { print("ID:", id, "Value:", value); }}results = DB\query "SELECT * FROM test_table"for [id, value] in *results print "ID:", id, "Value:", value 3.5 更新和删除数据 可以使用 exec 方法执行更新和删除操作: LuaTealTypeScriptYueScript-- 更新数据local rowsAffected = DB:exec("UPDATE test_table SET value = ? WHERE id = ?", {"Hello Dora", 1})print("更新了", rowsAffected, "行")-- 删除数据rowsAffected = DB:exec("DELETE FROM test_table WHERE id = ?", {2})print("删除了", rowsAffected, "行")-- 更新数据local rowsAffected = DB:exec("UPDATE test_table SET value = ? WHERE id = ?", {"Hello Dora", 1})print("更新了", rowsAffected, "行")-- 删除数据rowsAffected = DB:exec("DELETE FROM test_table WHERE id = ?", {2})print("删除了", rowsAffected, "行")// 更新数据let rowsAffected = DB.exec("UPDATE test_table SET value = ? WHERE id = ?", ["Hello Dora", 1]);print("更新了", rowsAffected, "行");// 删除数据rowsAffected = DB.exec("DELETE FROM test_table WHERE id = ?", [2]);print("删除了", rowsAffected, "行");-- 更新数据rowsAffected = DB\exec "UPDATE test_table SET value = ? WHERE id = ?", ["Hello Dora", 1]print "更新了", rowsAffected, "行"-- 删除数据rowsAffected = DB\exec "DELETE FROM test_table WHERE id = ?", [2]print "删除了", rowsAffected, "行" 4. 事务处理 事务是一组要么全部执行并执行成功. 要么遇到错误就全部都不执行的操作。在 Dora SSR 中,可以使用 transaction 方法来执行事务: LuaTealTypeScriptYueScriptlocal sqlStatements = { "INSERT INTO test_table (id, value) VALUES (3, 'Dora')", "INSERT INTO test_table (id, value) VALUES (4, 'SSR')"}local transactionSuccess = DB:transaction(sqlStatements)print(transactionSuccess and "事务成功" or "事务失败")local sqlStatements = { "INSERT INTO test_table (id, value) VALUES (3, 'Dora')", "INSERT INTO test_table (id, value) VALUES (4, 'SSR')"}local transactionSuccess = DB:transaction(sqlStatements)print("事务成功")const sqlStatements = [ "INSERT INTO test_table (id, value) VALUES (3, 'Dora')", "INSERT INTO test_table (id, value) VALUES (4, 'SSR')"];const transactionSuccess = DB.transaction(sqlStatements);print(transactionSuccess ? "事务成功" : "事务失败");sqlStatements = [ "INSERT INTO test_table (id, value) VALUES (3, 'Dora')", "INSERT INTO test_table (id, value) VALUES (4, 'SSR')"]transactionSuccess = DB\transaction sqlStatementsprint transactionSuccess and "事务成功" or "事务失败" 5. 异步操作 为了不阻塞主线程,Dora SSR 提供了异步操作的方法,如 insertAsync. queryAsync 和 execAsync。这些方法可以在后台线程中执行数据库操作。 LuaTealTypeScriptYueScriptthread(function() -- 异步插入数据 DB:insertAsync("test_table", { {5, "Async"}, {6, "Operation"} }) -- 异步查询数据 local asyncResults = DB:queryAsync("SELECT * FROM test_table") if asyncResults then for _, row in ipairs(asyncResults) do print("异步查询 - ID:", row[1], "Value:", row[2]) end endend)thread(function() -- 异步插入数据 DB:insertAsync("test_table", { {5, "Async"}, {6, "Operation"} }) -- 异步查询数据 local asyncResults = DB:queryAsync("SELECT * FROM test_table") if not asyncResults is nil then for _, row in ipairs(asyncResults) do print("异步查询 - ID:", row[1], "Value:", row[2]) end endend)thread(() => { // 异步插入数据 DB.insertAsync("test_table", [ [5, "Async"], [6, "Operation"] ]); // 异步查询数据 const asyncResults = DB.queryAsync("SELECT * FROM test_table"); if (asyncResults) { for (const [id, value] of asyncResults) { print("异步查询 - ID:", id, "Value:", value); } }});thread -> -- 异步插入数据 DB\insertAsync "test_table", [ [5, "Async"], [6, "Operation"] ] -- 异步查询数据 asyncResults = DB\queryAsync "SELECT * FROM test_table" for [id, value] in *asyncResults print "异步查询 - ID:", id, "Value:", value 6. 建立新的 Schema 在实际项目中,有时会需要建立一个新的 Schema 来分别存储管理游戏数据。而不是把数据都放在同一个默认库中。Schema 是一种数据库中的逻辑结构,可以看作是包含多个数据表的一个分组。可以使用 exec 方法来创建 Schema。 LuaTealTypeScriptYueScript-- 定义存储新的 Schema 数据的文件完整路径,必须是在引擎可写目录下local schemaFile = Path(Content.writablePath, "game_data.db")-- 创建 Schema,-- 当数据库文件不存在时会自动创建,-- 存在时会添加到当前数据库连接中DB:exec("ATTACH DATABASE '" .. schemaFile .. "' AS game_data")-- 在新的 Schema 中创建数据表并插入数据DB:exec("CREATE TABLE game_data.player (id INTEGER PRIMARY KEY, name TEXT)")DB:insert("game_data.player", {false, "Dora"})-- 查询新的 Schema 中的表数据DB:query("SELECT * FROM game_data.player")-- 卸载 Schema,使得新的 Schema 数据不再可以访问DB:exec("DETACH DATABASE game_data")-- 定义存储新的 Schema 数据的文件完整路径,必须是在引擎可写目录下local schemaFile = Path(Content.writablePath, "game_data.db")-- 创建 Schema,-- 当数据库文件不存在时会自动创建,-- 存在时会添加到当前数据库连接中DB:exec("ATTACH DATABASE '" .. schemaFile .. "' AS game_data")-- 在新的 Schema 中创建数据表并插入数据DB:exec("CREATE TABLE game_data.player (id INTEGER PRIMARY KEY, name TEXT)")DB:insert("game_data.player", {false, "Dora"})-- 查询新的 Schema 中的表数据DB:query("SELECT * FROM game_data.player")-- 卸载 Schema,使得新的 Schema 数据不再可以访问DB:exec("DETACH DATABASE game_data")// 定义存储新的 Schema 数据的文件完整路径,必须是在引擎可写目录下const schemaFile = Path(Content.writablePath, "game_data.db");// 创建 Schema,// 当数据库文件不存在时会自动创建,// 存在时会添加到当前数据库连接中DB.exec(`ATTACH DATABASE '${schemaFile}' AS game_data`);// 在新的 Schema 中创建数据表并插入数据DB.exec("CREATE TABLE game_data.player (id INTEGER PRIMARY KEY, name TEXT)");DB.insert("game_data.player", [false, "Dora"]);// 查询新的 Schema 中的表数据DB.query("SELECT * FROM game_data.player");// 卸载 Schema,使得新的 Schema 数据不再可以访问DB.exec("DETACH DATABASE game_data");-- 定义存储新的 Schema 数据的文件完整路径,必须是在引擎可写目录下schemaFile = Path(Content\writablePath, "game_data.db")-- 创建 Schema,-- 当数据库文件不存在时会自动创建,-- 存在时会添加到当前数据库连接中DB\exec "ATTACH DATABASE '#{schemaFile}' AS game_data"-- 在新的 Schema 中创建数据表并插入数据DB\exec "CREATE TABLE game_data.player (id INTEGER PRIMARY KEY, name TEXT)"DB\insert "game_data.player", [false, "Dora"]-- 查询新的 Schema 中的表数据DB\query "SELECT * FROM game_data.player"-- 卸载 Schema,使得新的 Schema 数据不再可以访问DB\exec "DETACH DATABASE game_data" 总结提示Dora SSR 引擎提供的默认 Schema 库会存储在代码 Path(Content.writablePath, "dora.db") 所对应的文件中。在访问数据表时,如果没有在表名前加前缀,即表示访问的是默认 Schema 中的数据表。如果需要创建新的 Schema 库,并存储在一个独立的更容易进行迁移使用的数据库文件中,可以使用 ATTACH DATABASE 和 DETACH DATABASE 来进行操作。 7. 将 Excel 数据导入数据库 在游戏开发中,通常会使用 Excel 表格来管理游戏数据。当 Excel 中的数据量较大,做数据关联等复杂的查询操作时,使用数据库会更加高效。Dora SSR 引擎提供了便捷的将 Excel 数据导入数据库的功能,方便开发者进行数据管理。 7.1 前置条件 数据表结构与 Excel 表格结构一致:确保数据库中的表结构(列名和列类型)与 Excel 工作表中的数据列对应。 Excel 文件格式:目前支持的 Excel 文件格式为 .xlsx。 7.2 示例步骤 下面我们将通过一个示例,演示如何将 Excel 数据导入到数据库中。 创建数据库表 假设我们有一个 Excel 文件 data.xlsx,其中包含一个工作表 Items,记录了游戏道具的信息,包括道具 ID. 名称和描述。首先,我们需要在数据库中创建对应的表: LuaTealTypeScriptYueScriptDB:exec([[ CREATE TABLE IF NOT EXISTS Items ( id INTEGER PRIMARY KEY, name TEXT, description TEXT )]])DB:exec([[ CREATE TABLE IF NOT EXISTS Items ( id INTEGER PRIMARY KEY, name TEXT, description TEXT )]])DB.exec(` CREATE TABLE IF NOT EXISTS Items ( id INTEGER PRIMARY KEY, name TEXT, description TEXT )`);DB\exec [[ CREATE TABLE IF NOT EXISTS Items ( id INTEGER PRIMARY KEY, name TEXT, description TEXT )]] 准备 Excel 文件 确保您的 Excel 文件 data.xlsx 位于项目的可访问路径下,工作表 Items 的第一行为列名,对应数据库表的列名: idnamedescription1SwordBasic sword2ShieldBasic shield......... 使用 DB.insertAsync 导入数据 LuaTealTypeScriptYueScriptthread(function() local success = DB:insertAsync( {"Items"}, "data.xlsx", 2 ) if success then print("Excel 数据导入成功!") else print("Excel 数据导入失败!") endend)thread(function() local success = DB:insertAsync( {"Items"}, "data.xlsx", 2 ) if success then print("Excel 数据导入成功!") else print("Excel 数据导入失败!") endend)thread(() => { const success = DB.insertAsync( ["Items"], "data.xlsx", 2 ); if (success) { print("Excel 数据导入成功!"); } else { print("Excel 数据导入失败!"); }});thread -> success = DB\insertAsync( ["Items",] "data.xlsx" 2 ) if success print "Excel 数据导入成功!" else print "Excel 数据导入失败!" 验证导入结果 您可以查询数据库,验证数据是否成功导入: LuaTealTypeScriptYueScriptlocal items = DB:query("SELECT * FROM Items")for _, item in ipairs(items) do print("ID:", item[1], "名称:", item[2], "描述:", item[3])endlocal items = DB:query("SELECT * FROM Items")if not items is nil then for _, item in ipairs(items) do print("ID:", item[1], "名称:", item[2], "描述:", item[3]) endendconst items = DB.query("SELECT * FROM Items");if (items) { for (const [id, name, description] of items) { print("ID:", id, "名称:", name, "描述:", description); }}items = DB\query "SELECT * FROM Items"for [id, name, description] in *items print "ID:", id, "名称:", name, "描述:", description 7.3 使用自定义工作表名称 如果您的 Excel 文件中,工作表名称与数据库表名不同,您可以指定对应关系: LuaTealTypeScriptYueScriptthread(function() local tableSheets = { {"Items", "GameItems"} -- 数据库表名为 "Items",对应的 Excel 工作表名为 "GameItems" } local success = DB:insertAsync( tableSheets, "data.xlsx", 2 ) if success then print("Excel 数据导入成功!") else print("Excel 数据导入失败!") endend)thread(function() local tableSheets = { {"Items", "GameItems"} -- 数据库表名为 "Items",对应的 Excel 工作表名为 "GameItems" } local success = DB:insertAsync( tableSheets, "data.xlsx", 2 ) if success then print("Excel 数据导入成功!") else print("Excel 数据导入失败!") endend)thread(() => { const tableSheets = [ ["Items", "GameItems"] // 数据库表名为 "Items",对应的 Excel 工作表名为 "GameItems" ]; const success = DB.insertAsync( tableSheets, "data.xlsx", 2 ); if (success) { print("Excel 数据导入成功!"); } else { print("Excel 数据导入失败!"); }});thread -> tableSheets = [ ["Items", "GameItems"] -- 数据库表名为 "Items",对应的 Excel 工作表名为 "GameItems" ] success = DB\insertAsync( tableSheets, "data.xlsx", 2 ) if success print "Excel 数据导入成功!" else print "Excel 数据导入失败!" 7.4 注意事项 数据类型匹配:确保 Excel 中的数据类型与数据库表的列类型兼容,例如,数值型数据应对应 INTEGER 或 REAL 类型,文本数据应对应 TEXT 类型。 日期和布尔值处理:Excel 中的日期和布 尔值需要在导入前进行适当的转换,以匹配数据库中的数据类型。 错误处理:insertAsync 方法在导入过程中如果遇到错误,将返回 false。建议在实际应用中添加错误日志,捕获并处理可能的异常情况。 8. 完整示例代码 下面是一段完整的示例代码,我们将逐行进行解析。 LuaTealTypeScriptYueScriptlocal DB <const> = require("DB")local thread <const> = require("thread")-- 使用事务建立一张表并插入初始化数据local sqls = { "DROP TABLE IF EXISTS test", "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", { "INSERT INTO test VALUES(?, ?)", { {false, "hello"}, {false, "world"}, {false, "ok"} } }}local result = DB:transaction(sqls)print(result and "Success" or "Failure")-- 检查表是否存在print(DB:exist("test"))-- 查询并打印数据p(DB:query("SELECT * FROM test", true))-- 删除和更新数据print("row changed:", DB:exec("DELETE FROM test WHERE id > 1"))print("row changed:", DB:exec("UPDATE test SET value = ? WHERE id = 1", {"hello world!"}))-- 进行异步操作thread(function() -- 异步插入数据 print("insert async") local data = {} local count = 1 for k in pairs(_G) do data[count] = {false, k} count = count + 1 end p(DB:insertAsync("test", data)) -- 异步查询数据 print("query async...") local items = DB:queryAsync("SELECT value FROM test WHERE value NOT LIKE 'hello%' ORDER BY value ASC") local rows = {} if items then count = 1 for i = 1, #items do local item = items[i] rows[count] = item[1] count = count + 1 end end p(rows)end)local DB <const> = require("DB")local thread <const> = require("thread")-- 使用事务建立一张表并插入初始化数据local sqls = { "DROP TABLE IF EXISTS test", "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", { "INSERT INTO test VALUES(?, ?)", { {false, "hello"}, {false, "world"}, {false, "ok"} } }}local result = DB:transaction(sqls)print(result and "Success" or "Failure")-- 检查表是否存在print(DB:exist("test"))-- 查询并打印数据p(DB:query("SELECT * FROM test", true))-- 删除和更新数据print("row changed:", DB:exec("DELETE FROM test WHERE id > 1"))print("row changed:", DB:exec("UPDATE test SET value = ? WHERE id = 1", {"hello world!"}))-- 进行异步操作thread(function() -- 异步插入数据 print("insert async") local data = {} local count = 1 for k in pairs(_G as {string: any}) do data[count] = {false, k} count = count + 1 end p(DB:insertAsync("test", data)) -- 异步查询数据 print("query async...") local items = DB:queryAsync("SELECT value FROM test WHERE value NOT LIKE 'hello%' ORDER BY value ASC") local rows = {} if not items is nil then count = 1 for i = 1, #items do local item = items[i] rows[count] = item[1] count = count + 1 end end p(rows)end)import { DB, thread, SQL } from "Dora";// 使用事务建立一张表并插入初始化数据const sqls: SQL[] = [ "DROP TABLE IF EXISTS test", "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", [ "INSERT INTO test VALUES(?, ?)", [ [false, "hello"], [false, "world"], [false, "ok"] ] ]];const result = DB.transaction(sqls);print(result ? "Success" : "Failure");// 检查表是否存在print(DB.exist("test"));// 查询并打印数据p(DB.query("SELECT * FROM test", true));// 删除和更新数据print("row changed:", DB.exec("DELETE FROM test WHERE id > 1"));print("row changed:", DB.exec("UPDATE test SET value = ? WHERE id = 1", ["hello world!"]));// 进行异步操作thread(() => { // 异步插入数据 print("insert async"); const data = []; let count = 1; for (const k in _G) { data[count] = [false, k]; count++; } p(DB.insertAsync("test", data)); // 异步查询数据 print("query async..."); const items = DB.queryAsync("SELECT value FROM test WHERE value NOT LIKE 'hello%' ORDER BY value ASC"); const rows = []; if (items) { for (let i = 0; i < items.length; i++) { const item = items[i]; rows.push(item[0]); } } p(rows);});_ENV = Dora-- 使用事务建立一张表并插入初始化数据sqls = [ "DROP TABLE IF EXISTS test", "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", [ "INSERT INTO test VALUES(?, ?)", [ [false, "hello"], [false, "world"], [false, "ok"] ] ]]result = DB\transaction sqlsprint result and "Success" or "Failure"-- 检查表是否存在print DB\exist "test"-- 查询并打印数据p DB\query "SELECT * FROM test", true-- 删除和更新数据print "row changed:", DB\exec "DELETE FROM test WHERE id > 1"print "row changed:", DB\exec "UPDATE test SET value = ? WHERE id = 1", ["hello world!",]-- 进行异步操作thread -> -- 异步插入数据 print "insert async" data = [] for k in pairs _G data[] = [false, k] p DB\insertAsync "test", data -- 异步查询数据 print "query async..." items = DB\queryAsync "SELECT value FROM test WHERE value NOT LIKE 'hello%' ORDER BY value ASC" rows = [] for i = 1, #items item = items[i] rows[] = item[1] p rows 8.1 代码解析 导入模块: LuaTealTypeScriptYueScriptlocal DB <const> = require("DB")local thread <const> = require("thread")local DB <const> = require("DB")local thread <const> = require("thread")import { DB, thread, SQL } from "Dora";_ENV = Dora DB 模块用于数据库操作。 thread 模块用于创建异步线程。 定义 SQL 语句列表: LuaTealTypeScriptYueScriptlocal sqls = { "DROP TABLE IF EXISTS test", "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", { "INSERT INTO test VALUES(?, ?)", { {false, "hello"}, -- 使用 false 作为数据库 NULL 值占位,id 会自动增长 {false, "world"}, {false, "ok"} } }}local sqls = { "DROP TABLE IF EXISTS test", "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", { "INSERT INTO test VALUES(?, ?)", { {false, "hello"}, -- 使用 false 作为数据库 NULL 值占位,id 会自动增长 {false, "world"}, {false, "ok"} } }}const sqls: SQL[] = [ "DROP TABLE IF EXISTS test", "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", [ "INSERT INTO test VALUES(?, ?)", [ [false, "hello"], // 使用 false 作为数据库 NULL 值占位,id 会自动增长 [false, "world"], [false, "ok"] ] ]];sqls = [ "DROP TABLE IF EXISTS test", "CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)", [ "INSERT INTO test VALUES(?, ?)", [ [false, "hello"], -- 使用 false 作为数据库 NULL 值占位,id 会自动增长 [false, "world"], [false, "ok"] ] ]] 删除名为 test 的表(如果存在)。 创建名为 test 的表,包含 id 和 value 两列。 插入三条数据,其中 id 因为数据表被创建为主键,会自动增长(使用 false 代表数据库 NULL 值占位),value 分别为 "hello". "world". "ok"。 执行事务: LuaTealTypeScriptYueScriptlocal result = DB:transaction(sqls)print(result and "Success" or "Failure")local result = DB:transaction(sqls)print(result and "Success" or "Failure")const result = DB.transaction(sqls);print(result ? "Success" : "Failure");result = DB\transaction sqlsprint result and "Success" or "Failure" 使用 transaction 方法执行一组 SQL 语句,保证原子性。 输出事务执行结果。 检查表是否存在: LuaTealTypeScriptYueScriptprint(DB:exist("test"))print(DB:exist("test"))print(DB.exist("test"));print DB\exist "test" 检查 test 表是否存在。 查询并打印数据: LuaTealTypeScriptYueScriptp(DB:query("SELECT * FROM test", true))p(DB:query("SELECT * FROM test", true))p(DB.query("SELECT * FROM test", true));p DB\query "SELECT * FROM test", true 查询 test 表中的所有数据,true 表示结果包含列名。 使用 p 函数(引擎内置的特殊打印函数)打印查询结果。 删除和更新数据: LuaTealTypeScriptYueScriptprint("row changed:", DB:exec("DELETE FROM test WHERE id > 1"))print("row changed:", DB:exec("UPDATE test SET value = ? WHERE id = 1", {"hello world!"}))print("row changed:", DB:exec("DELETE FROM test WHERE id > 1"))print("row changed:", DB:exec("UPDATE test SET value = ? WHERE id = 1", {"hello world!"}))print("row changed:", DB.exec("DELETE FROM test WHERE id > 1"));print("row changed:", DB.exec("UPDATE test SET value = ? WHERE id = 1", ["hello world!"]));print "row changed:", DB\exec "DELETE FROM test WHERE id > 1"print "row changed:", DB\exec "UPDATE test SET value = ? WHERE id = 1", ["hello world!",] 删除 id 大于 1 的数据。 更新 id 等于 1 的数据,将 value 改为 "hello world!"。 输出受影响的行数。 异步操作: LuaTealTypeScriptYueScriptthread(function() -- 异步插入数据 print("insert async") local data = {} local count = 1 for k in pairs(_G) do data[count] = {false, k} count = count + 1 end p(DB:insertAsync("test", data)) -- 异步查询数据 print("query async...") local items = DB:queryAsync("SELECT value FROM test WHERE value NOT LIKE 'hello%' ORDER BY value ASC") local rows = {} if items then count = 1 for i = 1, #items do local item = items[i] rows[count] = item[1] count = count + 1 end end p(rows)end)thread(function() -- 异步插入数据 print("insert async") local data = {} local count = 1 for k in pairs(_G as {string: any}) do data[count] = {false, k} count = count + 1 end p(DB:insertAsync("test", data)) -- 异步查询数据 print("query async...") local items = DB:queryAsync("SELECT value FROM test WHERE value NOT LIKE 'hello%' ORDER BY value ASC") local rows = {} if not items is nil then count = 1 for i = 1, #items do local item = items[i] rows[count] = item[1] count = count + 1 end end p(rows)end)thread(() => { // 异步插入数据 print("insert async"); const data = []; let count = 1; for (const k in _G) { data[count] = [false, k]; count++; } p(DB.insertAsync("test", data)); // 异步查询数据 print("query async..."); const items = DB.queryAsync("SELECT value FROM test WHERE value NOT LIKE 'hello%' ORDER BY value ASC"); const rows = []; if (items) { for (let i = 0; i < items.length; i++) { const item = items[i]; rows.push(item[0]); } } p(rows);});thread -> -- 异步插入数据 print "insert async" data = [] for k in pairs _G data[] = [false, k] p DB\insertAsync "test", data -- 异步查询数据 print "query async..." items = DB\queryAsync "SELECT value FROM test WHERE value NOT LIKE 'hello%' ORDER BY value ASC" rows = [] for i = 1, #items item = items[i] rows[] = item[1] p rows 创建一个新线程,执行异步操作。 异步插入:将全局变量名插入到 test 表中。 异步查询:查询 value 不以 "hello" 开头的数据,按字母顺序排序。 处理结果:将查询结果中的 value 提取出来,存入 rows 表。 打印结果。 9. 总结 通过本教程,您应该已经掌握了如何使用 Dora SSR 引擎的 SQLite 数据库功能来进行基本的数据操作。利用这些接口,您可以高效地管理游戏中的各种数据,为玩家提供更丰富的游戏体验。 提示: 始终确保在执行数据库操作时,处理可能的错误情况。 使用事务可以确保数据操作的原子性,避免数据不一致。 下一步: 了解更多高级 SQL 语法,如 JOIN. 子查询等。关于 SQLite SQL 语法的详细信息,请参考 SQLite 官方文档。 学习如何优化数据库查询,提高性能。 探索如何在实际项目中组织和管理数据库代码。